<script setup>
let wavesId = new Date().getTime()
const emit = defineEmits(['onTap'])
const props = defineProps({
  wavesColor: {
    type: String,
    default: 'rgba(0, 0, 0, .1)'
  },
  itemClass: {
    type: String,
    default: ''
  },
  off: {
    type: Boolean,
    default: false
  }
})
const state = reactive({
  rippleTop: 0,
  rippleLeft: 0,
  field: {},
  active: false,
  wavesId: 'waves_' + wavesId
})
function onTap(e) {
  // 点击事件
  emit('onTap', e)
}
function onTouchstart(e) {
  // 触碰事件 触发波纹
  state.active = false
  if (props.off) {
    return
  }
  nextTick(() => {
    activeWaves(e)
  })
}
function activeWaves(e) {
  getClientRect().then((data) => {
    if (!data.height) {
      return
    }
    data.finalWidth = data.height > data.width ? data.height : data.width
    if (!data.finalWidth) {
      return
    }
    state.field = data
    state.rippleTop = e.touches[0].clientY - data.top - data.finalWidth / 2
    state.rippleLeft = e.touches[0].clientX - data.left - data.finalWidth / 2
    nextTick(() => {
      state.active = true
    })
  })
}
function getClientRect() {
  return new Promise((resolve) => {
    let query = document
      .querySelector('#' + state.wavesId)
      .getBoundingClientRect()
    resolve(query)
  })
}
</script>

<template>
  <div
    :id="state.wavesId"
    class="waves"
    :class="itemClass"
    @click="onTap"
    @touchstart="onTouchstart($event)"
  >
    <slot></slot>
    <div
      class="waves-ripple"
      :class="{ active: state.active }"
      :style="{
        top: state.rippleTop + 'px',
        left: state.rippleLeft + 'px',
        width: state.field.finalWidth + 'px',
        height: state.field.finalWidth + 'px',
        'background-color': wavesColor
      }"
    ></div>
  </div>
</template>

<style scoped lang="less">
.waves {
  position: relative;
  overflow: hidden;
  height: 100%;
  .waves-ripple {
    position: absolute;
    border-radius: 100%;
    background-clip: padding-box;
    pointer-events: none;
    user-select: none;
    transform: scale(0);
    opacity: 1;
  }
  .active {
    opacity: 0;
    transform: scale(2);
    transition: opacity 1.2s ease-out, transform 0.5s ease-out;
  }
}
</style>
